﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using PanGu;
using PatientInformationExtract.Components;
using System.Threading;
using PatientInformationExtract.MainInterface.Models.XMLCS;
using System.Windows;


namespace PatientInformationExtract.MainInterface.Models
{
    public class ExportModel : ModelBase
    {
        private List<string> _exportList;
        private string _exportPath;
        private int _exportInterval;
        private bool _isEncoded;
        private int _failedCount;
        private EventLog _eventLog;
        private DateTime _startTime;
        private bool _isOpenFileAfterExport;
        private bool _isTranslatedToEnglish;
        private bool _isSynonymReplaced;
        private bool _isUsedTranslator;
        private List<Type> _parseComponentTypes;

        public ExportModel(ModelBase parentModel, List<string> exportList, int exportInterval, string exportPath)
            : base(parentModel)
        {
            this._exportList = exportList;
            this._exportInterval = exportInterval;
            this._exportPath = exportPath;
            _failedCount = 0;
        }

        public ExportModel(List<string> exportList, int exportInterval, string exportPath)
            : this(null, exportList, exportInterval, exportPath)
        {
        }

        public delegate void ExportStatusUpdateHandler(int currentCount, string nextFolderPath);
        public event ExportStatusUpdateHandler ExportStatusUpdateEvent;

        public delegate void ExportFinishedHandler(TimeSpan consumingTime);
        public event ExportFinishedHandler ExportFinishedEvent;

        private void RenewEventLog()
        {
            this._eventLog = new EventLog(Singleton<MainInterfaceModel>.Instance.ExcelWorkBooks);
            this._eventLog.Option.IsEncoded = this._isEncoded;
            this._eventLog.Option.IsTranslatedToEnglish = this._isTranslatedToEnglish;
            this._eventLog.Option.IsSynonymReplaced = this._isSynonymReplaced;
            this._eventLog.Option.IsUsedTranslator = this._isUsedTranslator;
            this._eventLog.Option.ParseComponentType = this._parseComponentTypes;
        }

        public void Export(bool isOpenFileAfterExport, bool isEncoded, bool isTranslatedToEnglish, bool isSynonymReplaced, bool isUsedTranslator, List<Type> parseComponentTypes)
        {
            this._isOpenFileAfterExport = isOpenFileAfterExport;
            this._isEncoded = isEncoded;
            this._isTranslatedToEnglish = isTranslatedToEnglish;
            this._isSynonymReplaced = isSynonymReplaced;
            this._isUsedTranslator = isUsedTranslator;
            this._parseComponentTypes = parseComponentTypes;
            RenewEventLog();
            this._startTime = DateTime.Now;
            if (!Directory.Exists(this._exportPath))
            {
                Directory.CreateDirectory(this._exportPath);
            }
            if (this._isEncoded)
            {
                this._eventLog.EncodingDictionaryDoc.Save(this._exportPath + "Encoding.xml");
            }
            Logger.Clear();
            Logger.Info("Export started, " + this._exportList.Count.ToString() + " patient folders, export options: " + this._exportInterval.ToString() + " patients per XML file, encoded: " + this._isEncoded.ToString() + ".");
            ThreadPool.QueueUserWorkItem(PatientInfoInitialize, _exportList);
        }

        public void PatientInfoInitialize(object exportPathList)
        {
            int currentCount = 0;
            foreach (string path in (exportPathList as List<string>))
            {
                PatientInfo pi = _eventLog.AddPatientInfo();
                if (this.ExportStatusUpdateEvent != null)
                {
                    this.ExportStatusUpdateEvent(currentCount, path);
                }
                try
                {
                    pi.Initialize(path);
                }
                catch (Exception ex)
                {
                    Logger.ExportInfo("Export " + path + " failed, error message: " + ex.Message + ".", Logger.LogStatus.Failure);
                    _eventLog.DeletePatientInfoByFolderPath(path);
                    _failedCount++;
                }
                currentCount++;
                if (currentCount == this._exportList.Count)
                {
                    _eventLog.Update();
                    _eventLog.XMLDoc.Save(this._exportPath + "EventLog.xml");
                    if (this._isOpenFileAfterExport)
                    {
                        try
                        {
                            System.Diagnostics.Process.Start(this._exportPath + "EventLog.xml");
                        }
                        catch { }
                    }
                    Logger.ExportInfo("EventLog.xml exported.", Logger.LogStatus.Succeed);
                    Logger.Info("Export ended, " + _failedCount.ToString() + " folders failed, " + (this._exportList.Count - _failedCount).ToString() + " folders exported, uses " + (DateTime.Now - _startTime).ToString() + ".");
                    Logger.SaveAll(this._exportPath + "Logger.txt");
                }
                else
                {
                    if (currentCount % this._exportInterval == 0)
                    {
                        _eventLog.Update();
                        _eventLog.XMLDoc.Save(this._exportPath + @"EventLog(" + (currentCount % this._exportInterval).ToString() + @").xml");
                        if (this._isOpenFileAfterExport)
                        {
                            System.Diagnostics.Process.Start(this._exportPath + @"EventLog(" + (currentCount % this._exportInterval).ToString() + @").xml");
                        }
                        Logger.ExportInfo("EventLog(" + (currentCount % this._exportInterval).ToString() + @").xml exported.", Logger.LogStatus.Succeed);
                        RenewEventLog();
                    }
                }
            }
            if (this.ExportFinishedEvent != null)
            {
                this.ExportFinishedEvent(DateTime.Now - this._startTime);
            }
        }

    }
}
